﻿#pragma once
#include <DirectXMath.h>

namespace Base {
	using namespace DirectX;

	struct Vec3 {

		union
		{
			struct
			{
				float x;
				float y;
				float z;
			};
			XMFLOAT3 data;
		};

		Vec3() {}
		Vec3(float px, float py, float pz) :x(px), y(py), z(pz) {}
		void Set(float px, float py, float pz) {
			x = px;
			y = py;
			z = pz;
		}
		Vec3& operator=(const XMFLOAT3& v) {
			x = v.x;
			y = v.y;
			z = v.z;
			return *this;
		}
		Vec3& operator=(const XMVECTOR& v) {
			XMStoreFloat3(&data, v);
			return *this;
		}
		Vec3 operator+(const Vec3& other)const {
			return Vec3(x + other.x, y + other.y, z + other.z);
		}
		Vec3 operator-(const Vec3& other)const {
			return Vec3(x - other.x, y - other.y, z - other.z);
		}


		Vec3 operator*(float scalar)const {
			return Vec3(x * scalar, y * scalar, z * scalar);
		}

		Vec3 operator*(const Vec3& rhs)const {
			return Vec3(x * rhs.x, y * rhs.y, z * rhs.z);
		}

		Vec3 operator/(float scalar) const;
		float Dot(const Vec3& other) const {
			return x * other.x + y * other.y + z * other.z;
		}

		Vec3 Cross(const Vec3& other) const {
			return Vec3::Cross(*this, other);
		}

		float Length() const {
			return sqrtf(LengthSquare());
		}
		float LengthSquare()const {
			return x * x + y * y + z * z;
		}

		Vec3& Normalize();

		//-------------------------------
		// static 方法
		static Vec3 Zero() {
			return Vec3(0, 0, 0);
		}
		static Vec3 One() {
			return Vec3(1, 1, 1);
		}
		static Vec3 AxisZ() {
			return Vec3(0, 0, 1);
		}
		static Vec3 AxisY() {
			return Vec3(0, 1, 0);
		}
		static Vec3 AxisX() {
			return Vec3(1, 0, 0);
		}

		static float Dot(const Vec3& lhs, const Vec3& rhs) {
			return lhs.Dot(rhs);
		}

		static Vec3 Cross(const Vec3& lhs, const Vec3& rhs) {

			XMVECTOR l = XMLoadFloat3(&lhs.data);
			XMVECTOR r = XMLoadFloat3(&rhs.data);

			Vec3 result;
			XMStoreFloat3(&result.data, XMVector3Cross(l, r));
			return result;
		}

	};


	// 全局方法
	Vec3 operator-(const Vec3& rhs);
	Vec3 operator*(float scalar, const Vec3& rhs);
}

